package feizhou.untils.tools.treeNode;


import feizhou.untils.tools.ReflectTools;
import lombok.Getter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/*
 *
 * 树节点工具
 * @author  <a href="920786312@qq.com">周飞</a>
 * @since 2023/10/19 11:17
 */
@Getter
public class TreeNodeUtil<T> {

    private String parentIdName;//父节点id名称
    private String idName;//节点id名称
    private List<T> nodes;//节点数据
    private String childNodeName;//节点数据

    //父节点map，存储格式，Map<当前节点id,Set<子节点ID>>
    private Map<String, Set<String>> parentNodeMap = new HashMap<>();

    //存储格式，Map<当前节点id,当前节点>
    private Map<String, T> dataMap = new HashMap<>();

    //最上层的节点Id列表
    private Set<String> rootNodeIds = null;

    /*
     *
     * 构建实例化
     * @param nodes 节点列表
     * @param parentIdName parentId字段名称
     * @param idName  id字段名称
     * @param childNodeName 子节点字段名称
     * @return void
     * @author  <a href="920786312@qq.com">周飞</a>
     * @since 2023/10/19 12:41
     */
    public TreeNodeUtil(List<T> nodes, String parentIdName, String idName, String childNodeName) {
        this.parentIdName = parentIdName;
        this.idName = idName;
        this.nodes = nodes;
        this.childNodeName = childNodeName;
        init();
    }

    //初始化
    private void init() {
        nodes.forEach(e -> {
            String idValue = getIdValue(e);
            String parentIdValue = getParentIdValue(e);
            putMap(parentIdValue, idValue);
            dataMap.put(idValue, e);
        });
        //获取最上层的节点Id列表
        initRootNodeIds();
    }

    /*
     *
     * 放到 parentNodeMap 里面
     * @param parentIdValue
     * @param idValue
     * @return void
     * @author  <a href="920786312@qq.com">周飞</a>
     * @since 2023/10/19 13:06
     */
    private void putMap(String parentIdValue, String idValue) {
        Set<String> childNodes = parentNodeMap.get(parentIdValue);
        if (childNodes == null) {
            childNodes = new HashSet<>();
        }
        childNodes.add(idValue);
        parentNodeMap.put(parentIdValue, childNodes);
    }

    /**
     * 设置子节点的值
     *
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/10/19 12:43
     */
    private void setChildNodes(Object object, List<Object> childNodes) {
        ReflectTools.setValue(object, childNodeName, childNodes);
    }

    /**
     * 获取id值
     *
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/10/19 12:43
     */
    private String getIdValue(Object object) {
        Object value = ReflectTools.getValue(object, idName);
        if (value == null) {
            return null;
        }
        return value.toString();
    }

    /**
     * 获取ParentId值
     *
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/10/19 12:43
     */
    private String getParentIdValue(Object object) {
        Object value = ReflectTools.getValue(object, parentIdName);
        if (value == null) {
            return null;
        }
        return value.toString();
    }

    /**
     * 初始话最上层的节点Id列表
     *
     * @return java.util.List<java.lang.Object>
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/10/19 12:42
     */
    private void initRootNodeIds() {
        //总节点-所有子节点=最上层父节点id
        Set<String> parentIds = new HashSet<>();
        Set<String> childNodeIds = new HashSet<>();
        Set<Map.Entry<String, Set<String>>> entries = parentNodeMap.entrySet();
        entries.stream().forEach(e -> {
            parentIds.add(e.getKey());
            parentIds.addAll(e.getValue());
            childNodeIds.addAll(e.getValue());
        });
        //总节点-所有子节点=最上层父节点id
        parentIds.removeAll(childNodeIds);

        //最上层的节点Id列表
        Set<String> tempRootNodeIds = new HashSet<>();
        parentIds.forEach(e -> {
            tempRootNodeIds.addAll(parentNodeMap.get(e));
        });

        this.rootNodeIds = tempRootNodeIds;

    }

    /**
     * 构建树
     *
     * @return void
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/10/19 13:33
     */
    public List<T> buildTree() {
        List<T> list = new ArrayList<>();
        if (rootNodeIds == null) {
            return null;
        }
        rootNodeIds.forEach(e -> {
            //当前节点
            T node = dataMap.get(e);
            buildTree(node, e);
            list.add(node);
        });

        //清空引用
        parentNodeMap = null;
        parentIdName = null;
        idName = null;
        childNodeName = null;
        dataMap = null;
        rootNodeIds = null;
        return list;
    }

    /**
     * 构建树
     *
     * @param node
     * @return void
     * @author <a href="920786312@qq.com">周飞</a>
     * @since 2023/10/19 13:33
     */
    private <T> void buildTree(T node, String nodeId) {
        //子节点列表
        List<Object> childNodes = new ArrayList<>();
        Set<String> childNodeIds = parentNodeMap.get(nodeId);
        //没有子节点，就退出
        if (childNodeIds == null) {
            return;
        }

        for (String childNodeId : childNodeIds) {
            Object childNode = dataMap.get(childNodeId);
            //递归子节点
            buildTree(childNode, childNodeId);
            //添加子节点
            childNodes.add(childNode);
        }
        //设置子节点的值
        setChildNodes(node, childNodes);

    }


    public static void main(String[] args) {

        List<TreeNode> list = new ArrayList<>();
        list.add(new TreeNode(1, "z1", 0, null));
        list.add(new TreeNode(2, "z12", 1, null));
        list.add(new TreeNode(3, "z13", 1, null));
        list.add(new TreeNode(4, "z124", 2, null));
        list.add(new TreeNode(5, "z125", 2, null));
        list.add(new TreeNode(6, "c1", -1, null));


        TreeNodeUtil<TreeNode> TreeNodeUtil = new TreeNodeUtil(list, "parentId", "id", "childs");
        List<TreeNode> treeNodes = TreeNodeUtil.buildTree();
        System.out.println(treeNodes);


    }
}
